﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Pay.DTO;
using Pay.IService;
using Pay.Data;
using Pay.Service.Cache;
using Pay.TO;
using Pay.Core;

namespace Pay.Service {
	public class ProfitDayService : ServiceBase, IProfitDayService, IDisposable {
		private IUnitOfWork _iUnitOfWork;

		public ProfitDayService(IUnitOfWork iUnitOfWork) : base(iUnitOfWork) {
			_iUnitOfWork = iUnitOfWork;
		}

		public ItpPage<profit_day_dto> Get(ProfitDayQuery profitDayQuery) {
			Expression<Func<ProfitDay, bool>> filter = c => true;
			var start_date = profitDayQuery.start_date.ToUnix();
			if (profitDayQuery.start_date.HasValue && profitDayQuery.end_date.HasValue) {
				var end_date = profitDayQuery.end_date.Value.AddDays(1).ToUnix();
				filter = filter.And(c => c.CreateDate >= start_date && c.CreateDate <= end_date);
			} else if (profitDayQuery.start_date.HasValue && !profitDayQuery.end_date.HasValue)
				filter = filter.And(c => c.CreateDate >= start_date);
			else if (!profitDayQuery.start_date.HasValue && profitDayQuery.end_date.HasValue) {
				var end_date = profitDayQuery.end_date.Value.AddDays(1).ToUnix();
				filter = filter.And(c => c.CreateDate <= end_date);
			}
			if (profitDayQuery.status > 0)
				filter = filter.And(c => c.Status == profitDayQuery.status);
			if (profitDayQuery.pay_channel != PayChannel.None)
				filter = filter.And(c => c.PayChannel == profitDayQuery.pay_channel);
			var result = context.ProfitDays.FromCachePaged<ProfitDay, profit_day_dto>(profitDayQuery.page, profitDayQuery.size, filter, orderBy => orderBy.OrderByDescending(c => c.CreateDate), "ProfitDay");
			var itpPage = new ItpPage<profit_day_dto> { page = result.page, size = result.size, rows = result.rows, total_result = result.total_result };
			var sum = context.ProfitDays.Where(filter).GroupBy(c => c.PayChannel)
							 .Select(c => new { MerchantProfit = c.Sum(x => (decimal?)x.MerchantProfit) ?? 0, Profit = c.Sum(x => (decimal?)x.Profit ?? 0) }).FirstOrDefault();
			itpPage.merchant_amount = sum.MerchantProfit;
			itpPage.profit = sum.Profit;
			return itpPage;
		}

		public profit_day_dto Get(long id) {
			var query = context.ProfitDays.Where(c => c.Id == id);
			return query.FromCacheFirstOrDefault<ProfitDay, profit_day_dto>("ProfitDay");
		}

		public int Insert(profit_day_dto dto) {
			var dt = dto.create_date.ToUnix();
			if (!context.ProfitDays.Any(c => c.CreateDate == dt && c.PayChannel == dto.pay_channel)) {
				context.ProfitDays.Add(dto.ToDtoObject<ProfitDay>());
				int result = _iUnitOfWork.Commit("ProfitDay");
				return result;
			}
			return 0;
		}

		public int Update(profit_day_dto dto) {
			var model = context.ProfitDays.FindById(dto.id);
			dto.ToDtoObject(model);
			int result = _iUnitOfWork.Commit("ProfitDay");
			return result;
		}

		public int Delete(long id) {
			var model = context.ProfitDays.FindById(id);
			if (model.Status <= 1) {
				context.ProfitDays.Remove(model);
				int result = _iUnitOfWork.Commit("ProfitDay");
				return result;
			}
			return 0;
		}
	}
}
